import {
  Box,
  concatName,
  DictSelect,
  FieldTypes,
  Icon,
  mapField,
  useCall,
  useDictionary,
  useFieldCtx,
  useFormValue,
  useQueryValue,
  useSimpleMemo,
} from '@/components';
import {
  MAIN_RISK_TYPE,
  PRODUCT_TYPE_INSURE,
  PRODUCT_TYPES_PB,
  REFUSE_GENDER,
  REFUSE_SOCIAL_SECURITY,
  TIME_RISK_MARK,
} from '@/constants/options';
import { arrayUnique, boolean, enumToOptions, initialValueByQuery, isObject } from '@/utils';
import { Checkbox, Form, Select, Tooltip } from 'antd';
import moment from 'moment';
import React, { useContext, useEffect, useMemo, useRef } from 'react';
import { Context, useProductCode } from '.';
import ExemptionsSelect from './ExemptionsSelect';
import PremGuaranteedInput from './PremGuaranteedInput';
import AgeField from './AgeField';
import FormulaConfigInput from './FormulaConfigInput';

const scopeInsureVo = { scope: ['productAddVo', 'productInsureVo'] };
const scopeAttrVo = { scope: ['productAddVo', 'productAttrVo'] };

function joinComma(v) {
  return v?.filter(Boolean).join(',') ?? null;
}

function splitComma(v) {
  return { value: v?.split(',').filter(Boolean) ?? [] };
}

function createShowBy(name, value, compare) {
  compare ??= function compareAsString(a, b) {
    return `${a}` === `${b}`;
  };
  const scope = (isObject(this) ? this.scope : null) ?? [];
  return {
    preserve: false,
    getColProps(item, index, form) {
      const hidden = useFormValue(form, concatName(scope, name), (v) => !compare(v, value));
      return { hidden };
    },
  };
}

const useIsPB = (form) => {
  const productType = useFormValue(form, [...scopeAttrVo.scope, 'productType']);

  return PRODUCT_TYPES_PB.includes(productType);
};

const ageUnitProps = {
  placeholder: null,
  initialValue: 'A',
  options: [
    { value: 'A', label: '岁' },
    { value: 'D', label: '天' },
  ],
};

function CheckboxComboField({ component: Comp, checkbox: { name, label, effect, change, init }, value, ...rest }) {
  const [symbol, isInit] = useMemo(() => {
    const symbol = Symbol('initial');
    return [symbol, () => valueRef.current === symbol];
  });
  const valueRef = useRef(symbol);
  const form = useFieldCtx('form');
  const show = useFormValue(form, name, (v) => {
    const show = v === '1';
    if (isInit()) {
      init?.(value, form);
    } else if (valueRef.current !== v) {
      effect?.(value, show, form);
    }
    valueRef.current = v;
    return show;
  });

  return (
    <Box flex dir='col'>
      <Form.Item noStyle name={name} {...boolean()}>
        <Checkbox style={{ margin: '5px 0 8px' }} onChange={(e) => change?.(e.target.checked, form)}>
          <Tooltip title='电投/建议书制作时是否显示该字段'>
            {label}&nbsp;
            <Icon type='info-circle' fontSize={11} />
          </Tooltip>
        </Checkbox>
      </Form.Item>
      {show && <Comp {...rest} value={value ?? ''} />}
    </Box>
  );
}

export const basic = [
  [
    'productCode',
    '险种编码',
    null,
    {
      required: true,
      getFieldProps() {
        const readOnly = useQueryValue('action') === 'edit';
        return { readOnly };
      },
      rules: [
        {
          pattern: /^[a-zA-Z0-9][\x00-\x7f]*$/,
          message: '只允许输入大小写字母、数字和符号组合，不能以符号开头',
        },
        {
          pattern: /^\S*$/,
          message: '不能输入空格或换行符',
        },
      ],
    },
  ],
  ['productName', '险种名称', null, { required: true }],
  ['productCategory', '险种分类', 'dict', { required: true, code: 'agency', hides: [''] }],
  ['timeRiskMark', '长短险类型', 'select', { required: true, options: enumToOptions(TIME_RISK_MARK) }],
  [
    'productType',
    '主附险类型',
    'select',
    { required: true, initialValue: MAIN_RISK_TYPE, options: enumToOptions(PRODUCT_TYPE_INSURE) },
  ],
  ['companyName', '保险公司名称', null, { required: true, readOnly: true, ...initialValueByQuery('companyName') }],
  ['companyCode', '保险公司编码', null, { required: true, readOnly: true, ...initialValueByQuery('companyCode') }],
  [
    ['../', '../', 'dutyFlag'],
    '责任型附加险',
    'radio-group',
    {
      initialValue: '0',
      getColProps(item, index, form) {
        const hidden = useFormValue(
          form,
          ['productAddVo', 'productAttrVo', 'productType'],
          (v) => v === MAIN_RISK_TYPE,
        );
        return { hidden };
      },
      options: [
        { value: '1', label: '是' },
        { value: '0', label: '否' },
      ],
    },
  ],
].map(mapField, scopeAttrVo);

const breakLine = [null, null, 'hidden', { noStyle: true, colProps: { xs: 24, md: 24, xl: 24 } }];

export const condition = [
  breakLine,
  [
    'refuseGender',
    '性别限制',
    'select',
    { initialValue: '', getValueProps: (v) => ({ value: v ?? '' }), options: enumToOptions(REFUSE_GENDER) },
  ],
  ['initialAge', '初始年龄', AgeField, createShowBy.call(scopeAttrVo, 'productType', MAIN_RISK_TYPE)],
  [
    'minAllowAge',
    '最小投保年龄',
    'group',
    {
      compact: true,
      required: true,
      fields: [
        [null, 'box', { component: FormulaConfigInput, grow: true, formulaType: 'string' }],
        [['../', 'minAllowAgeUnit'], 'select', ageUnitProps],
      ],
    },
  ],
  [
    'maxAllowAge',
    '最大投保年龄',
    'group',
    {
      compact: true,
      required: true,
      fields: [
        [null, 'box', { component: FormulaConfigInput, grow: true, formulaType: 'string' }],
        [['../', 'maxAllowAgeUnit'], 'select', ageUnitProps],
      ],
    },
  ],
  [
    ['../', '../', 'guaranteedTypeRule'],
    '保险期间规则',
    'radio-group',
    {
      ...createShowBy.call(scopeAttrVo, 'productType', MAIN_RISK_TYPE, (a, b) => `${a}` !== `${b}`),
      initialValue: '0',
      getFieldProps(e, i, form) {
        const isPB = useIsPB(form);
        const value = useFormValue(form, e.name);
        useEffect(() => {
          if (!isPB && value === '2') {
            form.setFieldsValue({ guaranteedTypeRule: '0' });
          }
        }, [isPB, value]);
        const options2 = useRef([
          { value: '0', label: '同主险' },
          { value: '2', label: '同缴费期' },
          { value: '1', label: '无限制' },
        ]).current;

        return isPB ? { options: options2 } : null;
      },
      options: [
        { value: '0', label: '同主险' },
        { value: '1', label: '无限制' },
      ],
    },
  ],
  [
    ['../', '../', 'paymentTypeRule'],
    '缴费方式规则',
    'radio-group',
    {
      ...createShowBy.call(scopeAttrVo, 'productType', MAIN_RISK_TYPE, (a, b) => `${a}` !== `${b}`),
      initialValue: '0',
      options: [
        { value: '0', label: '同主险' },
        { value: '1', label: '无限制' },
      ],
    },
  ],
  [
    ['../', '../', 'paymentYearRule'],
    '缴费年限规则',
    'radio-group',
    {
      ...createShowBy.call(scopeAttrVo, 'productType', MAIN_RISK_TYPE, (a, b) => `${a}` !== `${b}`),
      initialValue: '0',
      getFieldProps(e, i, form) {
        const isPB = useIsPB(form);
        const value = useFormValue(form, e.name);
        useEffect(() => {
          if (!isPB && value === '2') {
            form.setFieldsValue({ paymentYearRule: '0' });
          }
        }, [isPB, value]);

        const options2 = useRef([
          { value: '0', label: '同主险' },
          { value: '2', label: '主险缴费期减1年' },
          { value: '1', label: '无限制' },
        ]).current;

        return isPB ? { options: options2 } : null;
      },
      options: [
        { value: '0', label: '同主险' },
        { value: '1', label: '无限制' },
      ],
    },
  ],
  /*[
    'isRecognizees',
    '是否多被保人',
    'radio-group',
    {
      initialValue: '0',
      options: [
        { value: '0', label: '否' },
        { value: '1', label: '是' },
      ],
    },
  ],
  [
    'recognizeesLimit',
    '多被保人限制',
    'input-number',
    {
      ...createShowBy.call(scopeInsureVo, 'isRecognizees', '1'),
      initialValue: 5,
      min: 2,
      step: 1,
    },
  ],
  [
    ['recognizeesType'],
    '多被保计划',
    'radio-group',
    {
      ...createShowBy.call(scopeInsureVo, 'isRecognizees', '1'),
      initialValue: '0',
      options: [
        { value: '0', label: '多人单计划' },
        { value: '1', label: '多人多计划' },
      ],
    },
  ],*/
  [['../', '../', 'guaranteedValue'], '终身标记', 'input-number', { min: 1 }],
  breakLine,

  [
    'refuseSocialSecurity',
    '社保条件',
    CheckboxComboField,
    {
      component: Select,
      initialValue: '',
      options: enumToOptions(REFUSE_SOCIAL_SECURITY),
      checkbox: {
        label: '录入社保状态',
        name: 'enterSocialSecurity',
        change(show, form) {
          form.setFields([
            {
              name: ['productAddVo', 'productInsureVo', 'refuseSocialSecurity'],
              value: '',
            },
          ]);
        },
      },
    },
  ],
  [
    'refuseJobLevel',
    '限职业类别',
    'dict',
    {
      code: 'refuse_job',
      getValueFromEvent: joinComma,
      getValueProps: splitComma,
      mode: 'multiple',
    },
  ],
  [
    ['../', '../', 'enterJobLevelValue'],
    '职业等级',
    CheckboxComboField,
    {
      component(p) {
        const form = useFieldCtx('form');
        const levels = useFormValue(
          form,
          ['productAddVo', 'productInsureVo', 'refuseJobLevel'],
          (v) => v?.split(',') || [],
        );

        useEffect(() => {
          const { value, onChange } = p;
          if (onChange == null || value == null) return;
          const safeValue = value.filter((v) => levels.includes(v));
          if (safeValue.length !== value.length) {
            onChange(safeValue);
          }
        }, [levels]);

        const options = useDictionary('refuse_job');
        const options2 = useMemo(() => {
          return options.filter((v) => levels.includes(v.value));
        }, [options, levels]);

        return <Select {...p} mode='multiple' options={options2} />;
      },
      getItemProps(e, i, form) {
        const rules = useRef([
          {
            async validator(r, value) {
              if (form.getFieldValue('enterJobLevel') !== '1') return;
              if (!value?.length) throw '请输入职业等级';
            },
          },
        ]).current;
        return { rules };
      },
      getValueFromEvent: joinComma,
      getValueProps: splitComma,
      checkbox: {
        label: '录入职业等级',
        name: 'enterJobLevel',
        effect(v, show, form) {
          form.setFields([{ name: 'enterJobLevelValue', errors: [] }]);
        },
      },
    },
  ],
].map(mapField, scopeInsureVo);

const showByType = (type) => ({
  getColProps(item, index, form) {
    const hidden = useFormValue(
      form,
      ['productAddVo', 'productInsureVo', 'premiumAddType'],
      (v) => `${v}` !== `${type}`,
    );
    return { hidden };
  },
});

const toleranceRule = {
  getItemProps(e, i, form) {
    const valRef = useRef();
    valRef.current = useFormValue(form, [...scopeInsureVo.scope, 'singleCoverage']);

    return useRef({
      rules: [
        {
          message: '必须是单位保额/保费的整数倍',
          validator(r, value) {
            const singleCoverage = valRef.current;
            if (!value || !singleCoverage) return Promise.resolve();
            if (value % singleCoverage > 0) return Promise.reject(new Error(`必须是单位保额/保费的整数倍`));
          },
        },
      ],
    }).current;
  },
};

export const premium = [
  /** */
  ['premiumAddType', '销售方式', 'dict', { initialValue: '0', code: 'salesMethods' }],

  /** premiumAddType === 0 基于保额  ETF */
  ['defaultCoverage', '默认保额', FormulaConfigInput, { required: true, formulaType: 'string', ...showByType(0) }],
  ['singleCoverage', '单位保额', FormulaConfigInput, { required: true, formulaType: 'string', ...showByType(0) }],
  ['tolerance', '增减幅度', FormulaConfigInput, { formulaType: 'string', ...showByType(0) }],
  ['minPremiumLimitValue', '最低保费', FormulaConfigInput, { required: true, formulaType: 'string', ...showByType(0) }],
  ['minPremiumLimit', '最低保额', FormulaConfigInput, { required: true, formulaType: 'string', ...showByType(0) }],
  ['maxPremiumLimit', '最高保额', FormulaConfigInput, { required: true, formulaType: 'string', ...showByType(0) }],

  /** premiumAddType === 2 基于保费 FTE */
  ['defaultPremium', '默认保费', FormulaConfigInput, { required: true, formulaType: 'string', ...showByType(2) }],
  ['singleCoverage', '单位保费', FormulaConfigInput, { required: true, formulaType: 'string', ...showByType(2) }],
  ['tolerance', '增减幅度', FormulaConfigInput, { formulaType: 'string', ...showByType(2) }],
  ['minPremiumLimitValue', '最低保额', FormulaConfigInput, { required: true, formulaType: 'string', ...showByType(2) }],
  ['minPremiumLimit', '最低保费', FormulaConfigInput, { required: true, formulaType: 'string', ...showByType(2) }],
  ['maxPremiumLimit', '最高保费', FormulaConfigInput, { required: true, formulaType: 'string', ...showByType(2) }],

  /** premiumAddType === 1 基于保单量 NTF */
  ['maxPolicyNum', '最大保单量', 'input-number', { required: true, min: 0, ...showByType(1) }],
  ['singleCoverage', '每单保额', 'input-number', { required: true, min: 0, ...showByType(1) }],
].map(mapField, scopeInsureVo);

/** 责任选项类型 */
export const dutyValueMap = {
  // 可选
  selectable: '[{"code":"1","value":"否"},{"code":"0","value":"是"}]',
  // 必选
  required: '[{"code":"0","value":"是"}]',
};

export const dutyRulesMap = {
  deductible: '免赔额',
  privateRatio: '自付比例',
  coverage: '赔付限额',
  payoutRatio: '赔付比例',
};

export const dutyItem = (...scope) =>
  [
    ['dutyCode', null, 'hidden', { noStyle: true }],
    [
      'dutyName',
      '责任名称',
      null,
      {
        extra: (
          <Form.Item name={[...scope, 'dutyCode']} noStyle>
            <FieldTypes.plain />
          </Form.Item>
        ),
      },
    ],
    [
      'dutyValue',
      '是否可选',
      'radio-group',
      {
        initialValue: dutyValueMap.selectable,
        options: [
          { value: dutyValueMap.selectable, label: '可选' },
          { value: dutyValueMap.required, label: '必选' },
        ],
      },
    ],
    // ['contPlanCode', '保障计划编码'],
    // ['contArea', '保障区域'],
    ['rules', '责任项', 'checkbox-group', { options: enumToOptions(dutyRulesMap) }],
  ].map(mapField, { scope });

export const dutyRule = (ruleCode, scope) =>
  [
    [
      [ruleCode, 'name'],
      '名称',
      null,
      { required: true, preserve: false, extra: ruleCode, initialValue: dutyRulesMap[ruleCode] },
    ],
    [
      [ruleCode, 'values'],
      '选项',
      'select',
      {
        required: true,
        preserve: false,
        mode: 'tags',
        tokenSeparators: [',', '，', ' '],
        open: false,
      },
    ],
  ].map(mapField, { scope });

export const duty = [
  ['dutyName', '责任名称', null, { required: true, initialValue: '核心医疗保障' }],
  // ['contPlanCode', '保障计划编码'],
  // ['contArea', '保障区域'],
  [
    'rules',
    '责任项',
    (props) => (
      <Checkbox.Group {...props} onChange={useCall((value) => props.onChange?.(arrayUnique(['coverage', ...value])))} />
    ),
    {
      initialValue: ['coverage'],
      options: enumToOptions(dutyRulesMap),
    },
  ],
].map(mapField, { scope: ['duty'] });

export const addDutyRule = (exists = [], options = []) =>
  [
    [
      'ruleCode',
      '取值项目',
      'radio-group',
      {
        initialValue: 'coverage',
        options: [{ value: 'coverage', label: '赔付限额' }],
      },
    ],
    [
      'ruleValue',
      '匹配值',
      'checkbox-group',
      {
        required: true,
        options: options.map((v) => ({ value: v, label: v, disabled: exists.includes(v) })),
      },
    ],
  ].map(mapField);

export const formula = [
  /** 计算 */
  [
    ['formula', 'A1', 0],
    '基础保费',
    FormulaConfigInput,
    {
      fileType: 'A1',
      formulaType: 'file',
      fileRequired: true,
      getItemProps(item, index, form) {
        const isMC = useFormValue(form, ['productAddVo', 'productAttrVo', 'productCategory'], (v) => v === 'MC');
        const isFTE = useFormValue(form, [...scopeInsureVo.scope, 'premiumAddType'], (v) => v === '0');
        // const rules = useSimpleMemo(isMC ? [] : [{ required: true, message: '请配置保费费率' }]);

        const label = isFTE ? '基础保额' : '基础保费';
        return { label };
      },
    },
  ],
  [['formula', 'A4', 0], '现金价值', FormulaConfigInput, { fileType: 'A4', formulaType: 'file', fileRequired: true }],
  [['formula', 'A5', 0], '红利', FormulaConfigInput, { fileType: 'A5', formulaType: 'file', fileRequired: true }],
].map(mapField);

export const dutyFormula = (dutyCode, label) =>
  mapField([
    ['dutyFormula', dutyCode, 0],
    label,
    FormulaConfigInput,
    { dutyCode, fileType: 'A1', formulaType: 'file', fileRequired: true },
  ]);

export const clause = [
  [
    'effectiveBeginTime',
    '有效期',
    'named-range',
    {
      required: true,
      endName: 'effectiveEndTime',
      getFieldProps(item, index, form) {
        const lastEnd = useFormValue(form, ['clause', index - 1, 'effectiveEndTime']);
        const nextStart = useFormValue(form, ['clause', index + 1, 'effectiveBeginTime']);
        const disabledDate = useCall((date) => {
          if (!!lastEnd && date <= moment(lastEnd)) return true;
          return !!nextStart && date >= moment(nextStart);
        });

        return { disabledDate };
      },
    },
  ],
  [
    'termsUrl',
    '条款文件',
    'named-upload',
    {
      rules: [{ required: true, message: '请上传条款文件' }],
      fileNameProp: 'termsName',
      fileTypeProp: 'termsType',
      getFieldProps() {
        const { productCode } = useContext(Context);
        const data = { relationCode: productCode, fileType: 'CA' };
        return { data };
      },
    },
  ],
  ['termsName', '条款文件名', null, { required: true }],
].map(mapField);

export const premPay = [
  [
    'coreCode',
    '保司险种代码',
    null,
    {
      required: true,
      getItemProps() {
        const productCode = useProductCode();
        return { initialValue: productCode };
      },
    },
  ],

  ['guaranteedValue', '保障期限', PremGuaranteedInput, { required: true }],

  [
    'paymentType',
    '缴费方式',
    'dict',
    {
      code: 'payment_type',
      required: true,
      getValueFromEvent: joinComma,
      getValueProps: splitComma,
      mode: 'multiple',
    },
  ],

  [
    'paymentYears',
    '缴费年限',
    'dict',
    {
      required: true,
      code: 'payment_year',
      getValueFromEvent: joinComma,
      getValueProps: splitComma,
      mode: 'multiple',
    },
  ],
  [
    'pensionAge',
    '年金领取时间',
    'dict',
    {
      code: 'pensionAge',
      getValueFromEvent: joinComma,
      getValueProps: splitComma,
      mode: 'multiple',
    },
  ],
  [
    'minAge',
    '最小投保年龄',
    'group',
    {
      compact: true,
      required: true,
      width: '170px',
      fields: [
        [null, FormulaConfigInput, { /*component: FormulaConfigInput, grow: true,*/ formulaType: 'string' }],
        [['../', 'minAgeUnit'], 'select', ageUnitProps],
      ],
    },
  ],
  // ['minAge', '最小投保年龄', FormulaConfigInput, { required: true, formulaType: 'string' }],
  // [
  //   'minAgeUnit',
  //   '最小投保年龄单位',
  //   'select',
  //   {
  //     initialValue: 'A',
  //     options: [
  //       { value: 'D', label: '天' },
  //       { value: 'A', label: '岁' },
  //     ],
  //   },
  // ],

  [
    'maxAge',
    '最大投保年龄',
    'group',
    {
      compact: true,
      required: true,
      width: '170px',
      fields: [
        [null, 'box', { component: FormulaConfigInput, grow: true, formulaType: 'string' }],
        [['../', 'maxAgeUnit'], 'select', ageUnitProps],
      ],
    },
  ],
  // ['maxAge', '最大投保年龄', FormulaConfigInput, { required: true, formulaType: 'string' }],
  // [
  //   'maxAgeUnit',
  //   '最大投保年龄单位',
  //   'select',
  //   {
  //     initialValue: 'A',
  //     options: [
  //       { value: 'D', label: '天' },
  //       { value: 'A', label: '岁' },
  //     ],
  //   },
  // ],
].map(mapField);

export const exemption = [
  [
    'isExemptions',
    '是否可豁免',
    'radio-group',
    {
      required: true,
      initialValue: '0',
      getFieldProps(e, i, form) {
        const productType = useFormValue(form, [...scopeAttrVo.scope, 'productType']);
        const value = useFormValue(form, e.name);

        const options2 = useRef([
          { value: '1', label: '是', disabled: true },
          { value: '0', label: '否' },
        ]).current;
        useEffect(() => {
          if (productType === '2' && value === '1') {
            form.setFieldsValue({
              productAddVo: {
                productAttrVo: {
                  isExemptions: '0',
                },
              },
            });
          }
        }, [productType, value]);

        return productType === '2' ? { options: options2 } : null;
      },

      options: [
        { value: '1', label: '是' },
        { value: '0', label: '否' },
      ],
    },
  ],
  [
    'exemptionCodes',
    '可豁免产品',
    ExemptionsSelect,
    {
      getFieldProps(e, i, form) {
        const isPB = useIsPB(form);
        const value = useFormValue(form, e.name);
        useEffect(() => {
          if (!isPB && value) {
            form.setFieldsValue({
              productAddVo: {
                productAttrVo: {
                  exemptionCodes: null,
                },
              },
            });
          }
        }, [isPB, value]);
        return { disabled: !isPB };
      },
    },
  ],
].map(mapField, scopeAttrVo);

export const holderRule = [
  [
    'holderQuest',
    '---holderQuest',
    'dict',
    {
      code: 'refuse_job',
      getValueFromEvent: joinComma,
      getValueProps: splitComma,
      mode: 'multiple',
    },
  ],
  [
    'insuredQuest',
    '---insuredQuest',
    'dict',
    {
      code: 'refuse_job',
      getValueFromEvent: joinComma,
      getValueProps: splitComma,
      mode: 'multiple',
    },
  ],
  [
    'agentQuest',
    '---agentQuest',
    'dict',
    {
      code: 'refuse_job1',
      getValueFromEvent: joinComma,
      getValueProps: splitComma,
      mode: 'multiple',
    },
  ],
].map(mapField, scopeAttrVo);
